home *** CD-ROM | disk | FTP | other *** search
/ Apple Developer Connection Student Program / ADC Tools Sampler CD Disk 3 1999.iso / Metrowerks CodeWarrior / Java Support / Java_Source / Java2 / src / javax / swing / DefaultFocusManager.java < prev    next >
Encoding:
Java Source  |  1999-05-28  |  12.4 KB  |  369 lines  |  [TEXT/CWIE]

  1. /*
  2.  * @(#)DefaultFocusManager.java    1.11 98/08/26
  3.  *
  4.  * Copyright 1997, 1998 by Sun Microsystems, Inc.,
  5.  * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
  6.  * All rights reserved.
  7.  *
  8.  * This software is the confidential and proprietary information
  9.  * of Sun Microsystems, Inc. ("Confidential Information").  You
  10.  * shall not disclose such Confidential Information and shall use
  11.  * it only in accordance with the terms of the license agreement
  12.  * you entered into with Sun.
  13.  */
  14. package javax.swing;
  15.  
  16. import java.awt.event.KeyEvent;
  17. import java.awt.Component;
  18. import java.awt.Container;
  19. import java.awt.event.ActionEvent;
  20. import java.awt.Window;
  21. import java.awt.Dialog;
  22. import java.awt.Rectangle;
  23. import java.util.Stack;
  24.  
  25. /**
  26.  * Default swing focus manager implementation.
  27.  *
  28.  * @version 1.11 08/26/98
  29.  * @author Arnaud Weber
  30.  */
  31. public class DefaultFocusManager extends FocusManager {
  32.  
  33.     /** This method is called by JComponents when a key event occurs.
  34.      *  JComponent gives key events to the focus manager
  35.      *  first, then to key listeners, then to the keyboard UI dispatcher.
  36.      *  This method should look at the key event and change the focused
  37.      *  component if the key event matches the receiver's focus manager
  38.      *  hot keys. For example the default focus manager will change the
  39.      *  focus if the key event matches TAB or Shift + TAB.
  40.      *  The focus manager should call consume() on <b>anEvent</b> if 
  41.      *  <code>anEvent</code> has been processed. 
  42.      *  <code>focusedComponent</code> is the component that currently has
  43.      *  the focus.
  44.      *  Note: FocusManager will receive KEY_PRESSED, KEY_RELEASED and KEY_TYPED
  45.      *  key events. If one event is consumed, all other events type should be consumed.
  46.      */
  47.     Stack history = new Stack();
  48.  
  49.     public void processKeyEvent(Component focusedComponent,KeyEvent anEvent) {
  50.         if(anEvent.getKeyCode() == KeyEvent.VK_TAB || anEvent.getKeyChar() == '\t') {
  51.             /** If the focused component manages focus, let it do so
  52.              *  if control is not pressed 
  53.              */
  54.             if(focusedComponent instanceof JComponent) {
  55.                 JComponent fc = (JComponent) focusedComponent;
  56.                 if(fc.isManagingFocus()) {
  57.                     if(!((anEvent.getModifiers() & ActionEvent.CTRL_MASK) == 
  58.                        ActionEvent.CTRL_MASK))
  59.                         return;
  60.                 }
  61.             }
  62.  
  63.             /** If this is not a key press, consume and return **/
  64.             if(anEvent.getID() != KeyEvent.KEY_PRESSED){
  65.                 anEvent.consume();
  66.                 return;
  67.             }
  68.  
  69. //        System.out.println("\n\n******TAB pressed in processKeyEvent");
  70.             if((anEvent.getModifiers() & ActionEvent.SHIFT_MASK) == ActionEvent.SHIFT_MASK) 
  71.                 focusPreviousComponent(focusedComponent);
  72.             else
  73.                 focusNextComponent(focusedComponent);
  74.             anEvent.consume();
  75.         }
  76.     }
  77.  
  78.     /** Cause the focus manager to set the focus on the next focusable component **/
  79.     public void focusNextComponent(Component aComponent) {
  80.         if(aComponent instanceof JComponent) {
  81.             JComponent fc  = (JComponent) aComponent;
  82.             Component nc;
  83.             Container  root = getFocusRoot(fc);
  84.         if (!history.empty() && history.peek() != aComponent) {
  85.             history.removeAllElements();
  86.         }
  87.             if(root != null) {
  88.                 nc = getFocusableComponentAfter(fc,root,true);
  89.                 if(nc != null) {
  90.             if (history.empty() || history.peek() == aComponent) {
  91.               history.push(nc);
  92.             }
  93.                     if(nc instanceof JComponent)
  94.                         ((JComponent)nc).grabFocus();
  95.                     else
  96.                         nc.requestFocus();
  97.                 }
  98.             }
  99.         }
  100.     }
  101.  
  102.     /** Cause the focus manager to set the focus on the previous focusable component **/
  103.     public void focusPreviousComponent(Component aComponent) {
  104.  
  105.         if(aComponent instanceof JComponent) {
  106.             JComponent fc  = (JComponent) aComponent;
  107.             Component nc;
  108.             Container root = getFocusRoot(fc);
  109.  
  110.         if (!history.empty() && history.peek() == aComponent) {
  111.            history.pop();
  112.           if (!history.empty()) {
  113.         nc = (Component) history.peek();
  114.         if (nc instanceof JComponent)
  115.           ((JComponent)nc).grabFocus();
  116.         else
  117.           nc.requestFocus();
  118.         return;
  119.           }
  120.         }
  121.         
  122.         history.removeAllElements();
  123.  
  124.         if(root != null) {
  125.                 nc = getFocusableComponentAfter(fc,root,false);
  126.                 if(nc != null) {
  127.             if(nc instanceof JComponent)
  128.               ((JComponent)nc).grabFocus();
  129.             else
  130.               nc.requestFocus();
  131.                 }
  132.         }
  133.         }
  134.     }
  135.  
  136.     Container getFocusRoot(Component c) {
  137.         Container p;
  138.         for(p = c.getParent() ; p != null ; p = p.getParent()) {
  139.             if(((p instanceof JComponent) && ((JComponent)p).isFocusCycleRoot()) ||
  140.                (p instanceof Window) || (p instanceof Dialog))
  141.                 return p;
  142.         }
  143.         return null;
  144.     }
  145.  
  146.     private Component getFocusableComponentAfter(Component focusedComponent,
  147.                                                  Container rootContainer,
  148.                                                  boolean moveForward) {
  149.         Component nextComponent;
  150.         Component initialComponent;
  151.  
  152.         nextComponent = initialComponent = focusedComponent;
  153.         do {
  154.         if(moveForward) {
  155.           
  156.                 nextComponent = getNextComponent(nextComponent,rootContainer,true);
  157.         } else
  158.                 nextComponent = getPreviousComponent(nextComponent,rootContainer);
  159.             if(nextComponent == null)
  160.                 break;
  161.             if(nextComponent == initialComponent)
  162.                 break;
  163.         } while(!(nextComponent.isVisible() && 
  164.                   nextComponent.isFocusTraversable() && 
  165.                   nextComponent.isEnabled()));
  166.  
  167.         return nextComponent;
  168.     }
  169.  
  170.    private Component getNextComponent(Component component,
  171.                                       Container root,
  172.                                       boolean canGoDown) {
  173.        Component nsv = null;
  174.        
  175.        if(canGoDown && component.isVisible() &&
  176.           ( !(component instanceof JComponent) ||
  177.             !(((JComponent)component).isManagingFocus()) ) &&
  178.           ((component instanceof Container) && ((Container)component).getComponentCount() > 0)) {
  179.            return getFirstComponent((Container)component);
  180.        } else {
  181.            Container parent = component.getParent();
  182.            nsv = getComponentAfter(parent,component);
  183.            if(nsv != null)
  184.                return nsv;
  185.            if(parent == root)
  186.                return root;
  187.            else 
  188.                return getNextComponent(parent,root,false);
  189.        }
  190.    }
  191.  
  192.     private Component getPreviousComponent(Component component,Container root) {
  193.         Container parent = component.getParent();
  194.  
  195.         if(component == root)
  196.             return getDeepestLastComponent(root);
  197.         else {
  198.             Component nsv = getComponentBefore(parent,component);
  199.             if(nsv != null)
  200.                 return getDeepestLastComponent(nsv);
  201.             else
  202.                 return parent;
  203.         }
  204.     }
  205.  
  206.     private Component getDeepestLastComponent(Component component) {
  207.  
  208.         if(component.isVisible() &&
  209.             (((component instanceof JComponent)          && 
  210.              !((JComponent)component).isManagingFocus()) ||
  211.             !(component instanceof JComponent))         && 
  212.            ((component instanceof Container) && ((Container)component).getComponentCount() > 0)) {
  213.             return getDeepestLastComponent(getLastComponent((Container) component));
  214.         } else
  215.             return component;
  216.     }
  217.     
  218.     /** Return the first component that should receive the focus **/
  219.     public Component getFirstComponent(Container aContainer) {
  220.         Component orderedChildren[] = childrenTabOrder(aContainer);
  221.         if(orderedChildren.length > 0)
  222.             return orderedChildren[0];
  223.         else
  224.             return null;
  225.     }
  226.  
  227.     /** Return the last component that should receive the focus **/
  228.     public Component getLastComponent(Container aContainer) {
  229.         Component orderedChildren[] = childrenTabOrder(aContainer);
  230.         if(orderedChildren.length > 0)
  231.             return orderedChildren[orderedChildren.length - 1];
  232.         else
  233.             return null;
  234.     }
  235.  
  236.     /** Return the component that should receive the focus before aComponent **/
  237.     public Component getComponentBefore(Container aContainer,Component aComponent) {
  238.         Component comp;
  239.         if ((comp = inverseGetNextFocusable(aContainer, aComponent)) != null)
  240.             return comp;
  241.     return tabOrderPreviousComponent(aContainer, aComponent);
  242.     }
  243.  
  244.     /** Return the component the should receive the focus after aComponent **/
  245.     public Component getComponentAfter(Container aContainer,Component aComponent) {
  246.       Component nc;
  247.       if ((aComponent instanceof JComponent) &&
  248.       (nc = ((JComponent)aComponent).getNextFocusableComponent()) != null){
  249.       return nc;
  250.       }
  251.       return tabOrderNextComponent(aContainer, aComponent);
  252.     }
  253.  
  254.     
  255.     /** Return true if <code>a</code> should be before <code>b</code> in the
  256.      * "tab" order. Override this method if you want to change the automatic
  257.      * "tab" order. 
  258.      * The default implementation will order tab to give a left to right, top
  259.      * down order. Override this method if another order is required.
  260.      */
  261.     public boolean compareTabOrder(Component a,Component b) {
  262.         Rectangle bounds;
  263.         int ay,by;
  264.         int ax,bx;
  265.         if(a instanceof JComponent) {
  266.             ay = ((JComponent)a).getY();
  267.             ax = ((JComponent)a).getX();
  268.         } else {
  269.             bounds = a.getBounds();
  270.             ay = bounds.y;
  271.             ax = bounds.x;
  272.         }
  273.  
  274.         if(b instanceof JComponent) {
  275.             by = ((JComponent)b).getY();
  276.             bx = ((JComponent)b).getX();
  277.         } else {
  278.             bounds = b.getBounds();
  279.             by = bounds.y;
  280.             bx = bounds.x;
  281.         }
  282.  
  283.         if(Math.abs(ay - by) < 10) {
  284.             return (ax < bx);
  285.         }
  286.         return (ay < by);
  287.     }
  288.  
  289.     /** Return the component after comp according to compareTabOrder. If
  290.      * comp is the last component according to that order, return null.
  291.      */
  292.     
  293.     private Component tabOrderNextComponent(Container cont, Component cmp) {
  294.         Component orderedChildren[] = childrenTabOrder(cont);
  295.         int i;
  296.     int c = orderedChildren.length;
  297.  
  298.         /* since cmp is a child of cont, we know cont has at least one child */
  299.     if (c == 1) return null;
  300.  
  301.         for(i=0; i < c - 1 ; i++) 
  302.             if(orderedChildren[i] == cmp)
  303.                 return orderedChildren[i+1];
  304.         return null;
  305.     }
  306.  
  307.  
  308.     /** Return the component before comp according to compareTabOrder. If
  309.      * comp is the first component according to that order, return null.
  310.      */
  311.  
  312.     private Component tabOrderPreviousComponent(Container cont, Component cmp) {
  313.         Component orderedChildren[] = childrenTabOrder(cont);
  314.         int i;
  315.     int c = orderedChildren.length;
  316.  
  317.         /* since cmp is a child of cont, we know cont has at least one child */
  318.     if (c==1) return null;
  319.  
  320.         for(i=1; i < c ; i++) 
  321.             if(orderedChildren[i] == cmp)
  322.                 return orderedChildren[i-1];
  323.         return null;
  324.    }
  325.  
  326.     /** If there is a child c of Cont such that
  327.      * c.getNextFocusableComponent == comp, return that component.
  328.      * Otherwise, return null.
  329.      */
  330.  
  331.    private Component inverseGetNextFocusable(Container cont, Component comp) {
  332.       Component children[] = cont.getComponents();
  333.       int i;
  334.       int c;
  335.  
  336.         for(i=0,c = children.length ; i < c ; i++) {
  337.             if((children[i] instanceof JComponent) &&
  338.            (((JComponent)children[i]).getNextFocusableComponent()) == comp)
  339.           return children[i];
  340.     }
  341.     return null;
  342.     }
  343.  
  344.     Component[] childrenTabOrder(Container co) {
  345.         Component children[] = co.getComponents();
  346.         Component tmp;
  347.         int i,j,c;
  348.  
  349.         /** Get the tab order from the geometry **/
  350.         for(i=0,c = children.length ; i < c ; i++) {
  351.             for(j=i ; j < c ; j++) {
  352.                 if(i==j)
  353.                     continue;
  354.                 if(compareTabOrder(children[j],children[i])) {
  355.                     tmp = children[i];
  356.                     children[i] = children[j];
  357.                     children[j] = tmp;
  358.                 }                    
  359.             }
  360.         }
  361.     return children;
  362.     }
  363.   
  364.   void clearHistory() {
  365.     history.removeAllElements();
  366.   }
  367.  
  368. }
  369.